/*************************************************************************
 * Copyright 2008 David Almilli
 *  
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 *  
 *     http://www.apache.org/licenses/LICENSE-2.0 
 *      
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 **************************************************************************/
package com.tivo.hme.bananas;

import static com.tivo.hme.bananas.IBananasPlus.*;

import com.tivo.hme.bananas.BSkin.Element;
import com.tivo.hme.bananas.layout.Layout;
import com.tivo.hme.sdk.Resource;
import java.awt.Rectangle;
import java.text.Format;

public class BShuttleBarPlus extends BViewPlus {
	public static final String MODE_PLAY = "play";
	public static final String MODE_PAUSE = "pause";
	public static final String MODE_STOP = "stop";
    public static final String MODE_SLOW = "slow";
	public static final String MODE_FORWARD1 = "forward1";
	public static final String MODE_FORWARD2 = "forward2";
	public static final String MODE_FORWARD3 = "forward3";
	public static final String MODE_REVERSE1 = "reverse1";
	public static final String MODE_REVERSE2 = "reverse2";
	public static final String MODE_REVERSE3 = "reverse3";
	
	protected BView bar;
	protected BView barLeft;
	protected BTilesPlus barMiddle;
	protected BView barRight;
	protected BView shuttle;
	protected BView shuttleTop;
    protected BView shuttleBottom;
    protected BView shuttleMarker;
	protected BView shuttleMode;
    protected BTextPlus<String> minText;
    protected BTextPlus<String> maxText;
    protected BTextPlus<String> valueText;
	protected BTilesPlus ticks;
	protected BTilesPlus progress;
	protected int tickWidth;
	protected int progressWidth;
	
	protected String mode;
	protected int minValue;
	protected int maxValue;
	protected int value;
	protected int shuttleValue;
	protected boolean shuttleSnapToValue;
	protected Object animation;
	protected int tickSpacing;
	protected Format format;
    protected Object font;
    protected Object color;

	public BShuttleBarPlus(BView parent, int x, int y, int width) {
		this(parent, x, y, width, true);
	}

	public BShuttleBarPlus(BView parent, int x, int y, int width, boolean visible) {
		this(parent, x, y, width, 0, 3600, visible);
	}

	public BShuttleBarPlus(BView parent, int x, int y, int width, int minValue, int maxValue, boolean visible) {
		this(parent, ViewUtils.getBounds(parent, x, y, width, 
                H_SHUTTLEBAR_SHUTTLE_TOP, H_SHUTTLEBAR, H_SHUTTLEBAR_SHUTTLE_BOTTOM), minValue, maxValue, visible);
	}

    public BShuttleBarPlus(BView parent, Layout layout) {
        this(parent, layout, 0, 3600, true);
    }

    public BShuttleBarPlus(BView parent, Layout layout, int minValue, int maxValue, boolean visible) {
        this(parent, layout.getManager().defaultHeight(layout, 
                H_SHUTTLEBAR_SHUTTLE_TOP, H_SHUTTLEBAR, H_SHUTTLEBAR_SHUTTLE_BOTTOM).getBounds(), 
                minValue, maxValue, visible);
    }

	protected BShuttleBarPlus(BView parent, Rectangle bounds, int minValue, int maxValue, boolean visible) {
		super(parent, bounds.x, bounds.y, bounds.width, bounds.height, visible);

		this.minValue = minValue;
		this.maxValue = maxValue;
		this.shuttleSnapToValue = true;
		this.format = new TimeFormat();
		
		BSkin skin = getBApp().getSkin();
		Element eBar = skin.get(H_SHUTTLEBAR);
		Element eShuttleTop = skin.get(H_SHUTTLEBAR_SHUTTLE_TOP);
        Element eShuttleBottom = skin.get(H_SHUTTLEBAR_SHUTTLE_BOTTOM);
        Element eShuttleMarker = skin.get(H_SHUTTLEBAR_MARKER);
		Element eProgress = skin.get(H_SHUTTLEBAR_PROGRESS);
		Element eTick = skin.get(H_SHUTTLEBAR_TICK);

		int shuttleOffset = eShuttleTop.getHeight();
        int markerPadH = eShuttleMarker.getInt(P_PAD_H, 0);
        int markerPadV = eShuttleMarker.getInt(P_PAD_V, 0);
		int barCap = eBar.getInt(P_CAP, 0);
		int barPadV = eBar.getInt(P_PAD_V, 0);
		int barCenterWidth = eBar.getWidth()-2*barCap;
		
		//create the bar
		bar = new BView(this, 0, shuttleOffset, bounds.width, eBar.getHeight());

		Resource barRes = eBar.getResource();
		barLeft = new BView(bar, 0, 0, barCap, bar.getHeight());
		barLeft.setResource(barRes, RSRC_HALIGN_LEFT);

		barMiddle = new BTilesPlus(bar, barCap, 0, bar.getWidth()-2*barCap, bar.getHeight(), barCenterWidth, eBar.getHeight());
		barMiddle.setResource(barRes, RSRC_HALIGN_CENTER);

		barRight = new BView(bar, bar.getWidth()-barCap, 0, barCap, bar.getHeight());
		barRight.setResource(barRes, RSRC_HALIGN_RIGHT);
        
        Object font = getFont();
        Object color = getColor();
        minText = new BTextPlus<String>(bar, 0, 0, barCap, bar.getHeight());
        minText.setFont(font);
        minText.setColor(color);
        
        maxText = new BTextPlus<String>(bar, bar.getWidth()-barCap, 0, barCap, bar.getHeight());
        maxText.setFont(font);
        maxText.setColor(color);

		//create the progress area
		progressWidth = bounds.width-2*barCap;
		progress = new BTilesPlus(this, barCap, shuttleOffset+barPadV, 0, eProgress.getHeight(), eProgress.getWidth(), eProgress.getHeight());
		progress.setResource(eProgress.getResource());

		//create the tick marks
		this.tickWidth = eTick.getWidth();
		this.tickSpacing = (maxValue-minValue)/4;
		ticks = new BTilesPlus(this, barCap+tickWidth/2, shuttleOffset+barPadV, progressWidth-tickWidth, eTick.getHeight(), progressWidth/4, eTick.getHeight());
		ticks.setResource(eTick.getResource(), RSRC_HALIGN_RIGHT);
		
		//create the shuttle
        int shuttleWidth = eShuttleTop.getWidth();
        int shuttleHeight = eShuttleTop.getHeight() + eBar.getHeight() + eShuttleBottom.getHeight();
		shuttle = new BView(this, 0, 0, shuttleWidth, shuttleHeight);

		shuttleTop = new BView(shuttle, 0, 0, shuttle.getWidth(), eShuttleTop.getHeight());
        shuttleTop.setResource(eShuttleTop.getResource());

        shuttleMarker = new BView(shuttle, markerPadH, markerPadV, eShuttleMarker.getWidth(), eShuttleMarker.getHeight());
        shuttleMarker.setResource(eShuttleMarker.getResource());

        shuttleBottom = new BView(shuttle, 0, shuttleHeight-eShuttleBottom.getHeight(), 
                shuttleWidth, eShuttleBottom.getHeight());
        shuttleBottom.setResource(eShuttleBottom.getResource());

		shuttleMode = new BView(shuttle, 0, 0, shuttle.getWidth(), shuttle.getHeight());
        
        valueText = new BTextPlus<String>(shuttle, 0, 0, shuttle.getWidth(), shuttleOffset + barPadV);
        valueText.setFont(font);
        valueText.setColor(color);
        valueText.setFlags(RSRC_HALIGN_CENTER | RSRC_VALIGN_CENTER);

		setValue(minValue);
		
	}
	
	public void setShuttleVisible(boolean visible) {
		setShuttleVisible(visible, null);
	}
	
	public void setShuttleVisible(boolean visible, Resource anim) {
		shuttle.setVisible(visible, anim);
	}
	
	public boolean isShuttleVisible() {
		return shuttle.getVisible();
	}
	
	public int getMinValue() {
		return minValue;
	}
	
	public int getMaxValue() {
		return maxValue;
	}
	
	public void setRange(int minValue, int maxValue) {
		this.minValue = minValue;
		this.maxValue = maxValue;
        if (format != null) {
            minText.setValue(format.format(minValue));
            maxText.setValue(format.format(maxValue));
        }
		setValue(value);
	}

	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		int oldValue = this.value;
		int oldShuttleValue = this.shuttleValue;
		this.value = Math.min(Math.max(value, minValue), maxValue);
		if (isShuttleSnapToValue()) {
			this.shuttleValue = this.value;
		}
		if (oldValue != this.value || oldShuttleValue != this.shuttleValue) {
			refresh();
		}
	}

	public boolean isShuttleSnapToValue() {
		return shuttleSnapToValue;
	}

	public void setShuttleSnapToValue(boolean shuttleSnapToValue) {
		this.shuttleSnapToValue = shuttleSnapToValue;
		if (shuttleSnapToValue) {
			shuttleValue = value;
		}
		refresh();
	}

	public int getShuttleValue() {
		return shuttleValue;
	}

	public void setShuttleValue(int shuttleValue) {
		if (!isShuttleSnapToValue()) {
			int oldValue = this.shuttleValue;
			this.shuttleValue = Math.min(Math.max(shuttleValue, minValue), maxValue);
			if (oldValue != this.shuttleValue) {
				refresh();
			}
		}
	}
	
	protected void refresh() {
		setPainting(false);
		try {
			Resource anim = (animation != null) ? getResource(animation) : null;
			
			//set the progress meter
			float range = maxValue-minValue;
			float percent = value/range;
			progress.setSize((int)(progressWidth*percent), progress.getHeight(), anim);
			
			//set the shuttle location
			percent = shuttleValue/range;
			int offset = progress.getX() - shuttle.getWidth()/2;
			shuttle.setLocation(offset + (int)(progressWidth*percent), shuttle.getY(), anim);
			
			//set the tick spacing
			percent = tickSpacing/range;
			int tickTileWidth=(int)(progressWidth*percent);
			if (ticks.getTileWidth() != tickTileWidth) {
				//resize the tick marks
				ticks.setTileSize(tickTileWidth, ticks.getTileHeight());
			}
			
			//set the mode
			Element e = null;
			if (mode != null) {
				try {
					e = getBApp().getSkin().get(H_SHUTTLEBAR_MODE_PREFIX + mode);
				} catch (Exception t) {
					//the mode doesn't exist
				}
			}
			if (e != null) {
				Resource modeRes = e.getResource();
				if (modeRes != shuttleMode.getResource()) {
					//the mode has changed
					int padH = e.getInt(P_PAD_H, Integer.MIN_VALUE);
					int padV = e.getInt(P_PAD_V, Integer.MIN_VALUE);
					if (padH == Integer.MIN_VALUE) {
						padH = (shuttle.getWidth() - e.getWidth())/2;
					}
					if (padV == Integer.MIN_VALUE) {
						padV = (shuttle.getHeight() - e.getHeight())/2;
					}
					shuttleMode.setBounds(padH, padV, e.getWidth(), e.getHeight());
					shuttleMode.setResource(modeRes);
				
					if (!shuttleMode.getVisible()) {
						shuttleMode.setVisible(true);
					}
				}
			} else {
				if (shuttleMode.getVisible()) {
					shuttleMode.setVisible(false);
				}
			}
			
			//set the text value
            if (format != null) {
                minText.setValue(format.format(minValue));
                maxText.setValue(format.format(maxValue));
                valueText.setValue(format.format(value));
            } else {
                minText.setValue(null);
                maxText.setValue(null);
                valueText.setValue(null);
            }
			
		} finally {
			setPainting(true);
		}
	}

	public String getMode() {
		return mode;
	}

	public void setMode(String mode) {
		this.mode = mode;
		refresh();
	}

	public Object getAnimation() {
		return animation;
	}

	public void setAnimation(Object animation) {
		this.animation = animation;
	}

	public int getTickSpacing() {
		return tickSpacing;
	}

	public void setTickSpacing(int tickSpacing) {
		this.tickSpacing = tickSpacing;
		refresh();
	}

	public Format getFormat() {
		return format;
	}

	public void setFormat(Format format) {
		this.format = format;
        refresh();
	}

    public Object getFont() {
        if (font == null) {
            Element e = getBApp().getSkin().get(H_SHUTTLEBAR_FONT);
            if (e != null) {
                font = e.getResource();
            }
        }
        return font;
    }

    public void setFont(Object font) {
        this.font = font;
        minText.setFont(font);
        maxText.setFont(font);
        valueText.setFont(font);
    }

    public Object getColor() {
        if (color == null) {
            Element e = getBApp().getSkin().get(H_SHUTTLEBAR_COLOR);
            if (e != null) {
                color = e.getResource();
            }
        }
        return color;
    }

    public void setColor(Object color) {
        this.color = color;
        minText.setColor(color);
        maxText.setColor(color);
        valueText.setColor(color);
    }

}
